#include "qqmusic.h"
#include "ui_qqmusic.h"
#include<QGraphicsEffect>
#include<QMouseEvent>
#include<QJsonObject>
#include<QJsonArray>
#include<QChar>
#include"lrcpage.h"


QQMusic::QQMusic(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::QQMusic)
    ,currentIndex(-1)
{
    ui->setupUi(this);
    InitUi();
    // 初始化数据库
    initSQLite();
    //初始化音乐列表
    iniMUsicList();
    //初始化播放器
    initPlayer();   
    connectSignalAndslots();
}

QQMusic::~QQMusic()
{
    delete ui;
}


void QQMusic::InitUi()
{
    //去掉窗口边框
    setWindowFlag(Qt::WindowType::FramelessWindowHint);
    // 设置窗⼝背景透明，加上这个窗口的阴影才不会是黑边
    this->setAttribute(Qt::WA_TranslucentBackground);
    //设置主窗口图标
    setWindowIcon(QIcon(":/images/tubiao.png"));
    //取缔最大化按钮
    ui->max->setEnabled(false);

    //添加系统托盘
    QSystemTrayIcon*trayIcon=new QSystemTrayIcon(this);
    trayIcon->setIcon(QIcon(":/images/tubiao.png"));
    // 创建托盘菜单
    QMenu *trayMenu = new QMenu(this);
    trayMenu->addAction("还原", this, &QWidget::showNormal);
    trayMenu->addSeparator();
    trayMenu->addAction("退出", this, &QQMusic::quitQQMusic);
    // 将托盘菜单添加到托盘图标
    trayIcon->setContextMenu(trayMenu);
    trayIcon->show();
    //这个类就是设置窗口的阴影的类
    QGraphicsDropShadowEffect*ShadowEffect=new QGraphicsDropShadowEffect();
    //设置阴影的模糊半径
    ShadowEffect->setBlurRadius(10);
    //设置阴影的颜色
    ShadowEffect->setColor("#000000");
    //设置阴影相对于元素的位置
    ShadowEffect->setOffset(0,0);
    this->setGraphicsEffect(ShadowEffect);

    ui->rec->setIconAndText(":/images/rec.png","推荐",0);
    ui->radio->setIconAndText(":/images/radio.png","电台",1);
    ui->music->setIconAndText(":/images/music.png","音乐馆",2);
    ui->like->setIconAndText(":/images/like.png","我喜欢",3);
    ui->local->setIconAndText(":/images/local.png","本地下载",4);
    ui->recent->setIconAndText(":/images/recent.png","最近播放",5);
    ui->stackedWidget->setCurrentIndex(4);//设置打开程序默认在最近播放页面
    curPage=ui->localpage;
    // 本地下载BtForm动画默认显⽰
     ui->local->showAnimal(true);//只设置最近播放有动画播放
    randomPiction();
    srand(time(NULL));
    //recBox的上部分就只有一行
    ui->recMusicBox->initRecBoxUi(randomPiction(),1);
    //下部分则有两行
    ui->supplyMusicBox->initRecBoxUi(randomPiction(),2);

    //CommonPage配置

    ui->likepage->setCommonPageUI("我喜欢",":/images/ilikebg.png");

    ui->localpage->setCommonPageUI("本地下载",":/images/localbg.png");

    ui->recentpage->setCommonPageUI("最近播放",":/images/recentbg.png");

    ui->play->setIcon(QIcon(":/images/play_2.png")); // 默认为暂停图标
    ui->playMode->setIcon(QIcon(":/images/shuffle_2.png")); // 默认为随机播放
    //创建音量调节窗口并挂到对象树上
    volumeTool = new VolumeTool(this);

    // 创建lrc歌词窗⼝
    lrcPage = new LrcPage(this);
    lrcPage->hide();
    // lrcPage添加动画效果
    lrcAnimation = new QPropertyAnimation(lrcPage, "geometry", this);
    lrcAnimation->setDuration(250);
    lrcAnimation->setStartValue(QRect(10, 10+lrcPage->height(),
                                      lrcPage->width(), lrcPage->height()));
    lrcAnimation->setEndValue(QRect(10, 10, lrcPage->width(), lrcPage->height()));



}

void QQMusic::connectSignalAndslots()
{
    connect(ui->rec,&btForm::btClick,this,&QQMusic::onBtFormClicke);
    connect(ui->radio,&btForm::btClick,this,&QQMusic::onBtFormClicke);
    connect(ui->music,&btForm::btClick,this,&QQMusic::onBtFormClicke);
    connect(ui->like,&btForm::btClick,this,&QQMusic::onBtFormClicke);
    connect(ui->local,&btForm::btClick,this,&QQMusic::onBtFormClicke);
    connect(ui->recent,&btForm::btClick,this,&QQMusic::onBtFormClicke);
    // 关联CommonPage发射的updateLikeMusic信号
    connect(ui->likepage, &CommonPage::updateLikeMusic, this,&QQMusic::onUpdateLikeMusic);
    connect(ui->localpage, &CommonPage::updateLikeMusic, this,&QQMusic::onUpdateLikeMusic);
    connect(ui->recentpage, &CommonPage::updateLikeMusic, this,&QQMusic::onUpdateLikeMusic);
    //控制播放及上一曲，下一曲
    connect(ui->play,&QPushButton::clicked,this,&QQMusic::onPlayMusic);
    connect(ui->playUp, &QPushButton::clicked, this,&QQMusic::onPlayUpCliked);
    connect(ui->playDown, &QPushButton::clicked, this,&QQMusic::onPlayDownCliked);
    //播放全部
    connect(ui->likepage, &CommonPage::playAll, this, &QQMusic::onPlayAll);
    connect(ui->localpage, &CommonPage::playAll, this, &QQMusic::onPlayAll);
    connect(ui->recentpage, &CommonPage::playAll, this, &QQMusic::onPlayAll);
    // 处理likePage、localPage、recentPage中ListItemBox双击
    connect(ui->likepage, &CommonPage::playMusicByIndex, this,&QQMusic::playMusicByIndex);
    connect(ui->localpage, &CommonPage::playMusicByIndex, this,&QQMusic::playMusicByIndex);
    connect(ui->recentpage, &CommonPage::playMusicByIndex, this,&QQMusic::playMusicByIndex);
    //设置静音
    connect(volumeTool, &VolumeTool::setSilence, this,&QQMusic::setMusicSilence);
    // 设置⾳量⼤⼩
    connect(volumeTool, &VolumeTool::setMusicVolume, this,&QQMusic::setPlayerVolume);
    // 进度条拖拽
    connect(ui->processBar, &MusicSlider::setMusicSliderPosition, this,&QQMusic::onMusicSliderChanged);
    // 显⽰歌词窗⼝
    connect(ui->lrcWord, &QPushButton::clicked, this,&QQMusic::onLrcWordClicked);
    //最小化按钮
    connect(ui->min,&QPushButton::clicked,this,&QQMusic::on_min_clicked);
    //皮肤按钮
    connect(ui->skin,&QPushButton::clicked,this,&QQMusic::on_skin_clicked);

}

QJsonArray QQMusic::randomPiction()
{
    //推荐文本+推荐图片路径
    QVector<QString> vecImageName;
    vecImageName<<"001.png"<<"003.png"<<"004.png"<<"005.png"<<"006.png"
               <<"007.png"
              <<"008.png"<<"009.png"<<"010.png"<<"011.png"<<"012.png"
             <<"013.png"
            <<"014.png"<<"015.png"<<"016.png"<<"017.png"<<"018.png"
           <<"019.png"
          <<"020.png"<<"021.png"<<"022.png"<<"023.png"<<"024.png"
         <<"025.png"
        <<"026.png"<<"027.png"<<"028.png"<<"029.png"<<"030.png"
       <<"031.png"
      <<"032.png"<<"033.png"<<"034.png"<<"035.png"<<"036.png"
     <<"037.png"
    <<"038.png"<<"039.png"<<"040.png";
    //对上述图片进行打乱顺序
    std::random_shuffle(vecImageName.begin(), vecImageName.end());
    QJsonArray objArray;
    for (int i=0;i<vecImageName.size();i++)
    {
        QJsonObject obj;
        obj.insert("path", ":/images/rec/"+vecImageName[i]);
        // arg(i, 3, 10, QCchar('0'))
        // i：要放⼊%1位置的数据
        // 3:  三位数
        // 10：表⽰⼗进制数
        // QChar('0') ：数字不够三位，前⾯⽤字符 '0'填充
        QString strText=QString("推荐-%1").arg(i,3,10,QChar('0'));
        obj.insert("text",strText);
        objArray.append(obj);
    }
    return objArray;
}

//播放状态改变时图标切换
void QQMusic::onPlayStateChanged()
{
    if(player->state() == QMediaPlayer::PlayingState)
    {
        // 播放状态
        ui->play->setIcon(QIcon(":/images/play_on.png"));
    }
    else
    {
        // 暂停状态
        ui->play->setIcon(QIcon(":/images/play3.png"));
    }
}



void QQMusic::onUpdateLikeMusic(bool isLike, QString musicId)
{
    // 1. 找到该⾸歌曲，并更新对应Music对象信息
    auto it = musicList.findMusicById(musicId);
    if(it != musicList.end())
    {
        it->setIsLike(isLike);
    }
    // 2. 通知三个⻚⾯更新⾃⼰的数据
    ui->likepage->reFresh(musicList);
    ui->localpage->reFresh(musicList);
    ui->recentpage->reFresh(musicList);

}

void QQMusic::on_quit_clicked()
{
    hide();
}


//这个事件是当鼠标在窗口中按下时才会调用
void QQMusic::mousePressEvent(QMouseEvent *event)
{
    //这里的意思就是当鼠标移动的过程中点击了左键
    if(event->button()==Qt::LeftButton)
    {
        isDrag=true;
        //记录当时鼠标离窗口右上角的相对位置并返回
        dragPosition=event->globalPos()-geometry().topLeft();
        return;
    }
    //当上述条件不成立时就去调用父类
    QWidget::mousePressEvent(event);
}
//这个事件只会在鼠标移动时进行调用
void QQMusic::mouseMoveEvent(QMouseEvent* event)
{
    //这里表示当按下窗口的键是鼠标左键时才会触发
    if(Qt::LeftButton==event->buttons()&&isDrag)
    {
        //根据鼠标当前位置和初始偏移量移动窗口
        move(event->globalPos()-dragPosition);
        return;
    }
    QWidget::mouseMoveEvent(event);
}
void QQMusic::onBtFormClicke(int pageId)
{
    //创建一个Qlist来存放当前所有btForm按钮类型的对象
    QList<btForm*> buttonList = this->findChildren<btForm*>();
    for (auto btForm: buttonList)
    {
        if(btForm->getpageId() != pageId)
        {
            btForm->clearBackground();
        }
    }
    ui->stackedWidget->setCurrentIndex(pageId);
    // 点击btForm时，窗⼝不能拖拽
     isDrag = false;

}
//音量播放按钮的槽函数
void QQMusic::on_volume_clicked()
{
    //获取该按钮左上角的图标
    QPoint point=ui->volume->mapToGlobal(QPoint(0,0));
    //计算窗口左上角的位置，让该窗口显示在鼠标的正上方，鼠标位置，减去宽度的一般，以及一整个高度，就是窗口的左上角
    QPoint volumeLeftTop = point - QPoint(volumeTool->width()/2, volumeTool->height());
    // 微调窗⼝位置
    volumeLeftTop.setY(volumeLeftTop.y()+30);
    volumeLeftTop.setX(volumeLeftTop.x()+15);

    // 3. 移动窗⼝位置
    volumeTool->move(volumeLeftTop);
    // 4. 将窗⼝显⽰出来
    volumeTool->show();

}
//添加本地音乐
void QQMusic::  on_addLocal_clicked()
{
    //创建一个文件对话框
    QFileDialog filedialog(this);
    filedialog.setWindowTitle("添加本地音乐");

    //创建一个打开格式的文件对话框
    filedialog.setAcceptMode(QFileDialog::AcceptOpen);

    //设置对话框模式
    //只能选择模式，并且一次性能选择多个存在的文件
    filedialog.setFileMode(QFileDialog::ExistingFiles);

    //设置对话框的MIME过滤器
    QStringList mimeList;
    mimeList <<"application/octet-stream";
    filedialog.setMimeTypeFilters(mimeList);

    //设置对话框的默认打开路径，设置目录为当前工程所在目录
    QDir dir(QDir::currentPath());
    dir.cdUp();
    QString musicPath =dir.path()+"/QQMusic/musics/";
    filedialog.setDirectory(musicPath);

    //显示对话框，并接收返回值
    //模态对话框
    if(filedialog.exec()==QFileDialog::Accepted)
    {
        //切换到本地音乐，因为加载完成后的音乐需要在本地音乐显示
        ui->stackedWidget->setCurrentIndex(4);
        //获取对话框的返回值
        QList<QUrl> urls=filedialog.selectedUrls();

        musicList.addMusicByUrl(urls);
        // 更新到本地⾳乐列表
        ui->localpage->reFresh(musicList);
        ui->localpage->addMusicToPlayer(musicList,playList);
    }


}

void QQMusic::onPlayMusic()
{
    //如果处于播放中，点击按钮就会暂停
    if(QMediaPlayer::PlayingState==player->state())
    {
        player->pause();
    }
    //处于暂停中，点击按钮就会播放
    else if(QMediaPlayer::PausedState==player->state())
    {
        player->play();
    }
    //处于停止中，点击按钮就会播放
    else if(QMediaPlayer::StoppedState==player->state())
    {
        player->play();
    }
    //这几种状态都不是，说明出错了
    else
    {
        qDebug()<< player->errorString();
    }
}


///////////////////////////////////////////////////////////////////////////////////////////////////
//从这里开始设置播放模块
void QQMusic::initPlayer()
{
    //初始化媒体播放类
    player = new QMediaPlayer(this);
    playList = new QMediaPlaylist(this);
    // 设置播放模式：默认为循环播放
    playList->setPlaybackMode(QMediaPlaylist::Loop);
    //将播放列表设置给播放器
    player->setPlaylist(playList);
    //默认音量大小为20
    player->setVolume(20);
    connect(ui->playMode, &QPushButton::clicked, this,&QQMusic::onPlaybackModeCliked);
    connect(playList, &QMediaPlaylist::playbackModeChanged, this,&QQMusic::onPlaybackModeChanged);
    connect(player, &QMediaPlayer::stateChanged, this,&QQMusic::onPlayStateChanged);
    // 播放列表项发⽣改变，此时将播放⾳乐收藏到历史记录中
    connect(playList, &QMediaPlaylist::currentIndexChanged, this,&QQMusic::onCurrentIndexChanged);
    //播放位置发生改变，将已经播放的时间更新
    connect(player,&QMediaPlayer::durationChanged,this,&QQMusic::onDurationChanged);
    // 播放位置发⽣改变，即已经播放时间更新
    connect(player, &QMediaPlayer::positionChanged, this,&QQMusic::onpositionChanged);
    //关联QMediaPlayer::onMetaDataAvailableChangedChanged
    connect(player,&QMediaPlayer::metaDataAvailableChanged,this,&QQMusic::onMetaDataAvailableChangedChanged);
}


void QQMusic::onPlayUpCliked()
{
    playList->previous();
}

void QQMusic::onPlayDownCliked()
{
    playList->next();
}
//播放模式图标改变
void QQMusic::onPlaybackModeChanged(QMediaPlaylist::PlaybackMode playbackMode)
{
    if(playbackMode == QMediaPlaylist::Loop)
    {
        ui->playMode->setIcon(QIcon(":/images/list_play.png"));
    }
    else if(playbackMode == QMediaPlaylist::Random)
    {
        ui->playMode->setIcon(QIcon(":/images/shuffle_2.png"));
    }
    else if(playbackMode == QMediaPlaylist::CurrentItemInLoop)
    {
        ui->playMode->setIcon(QIcon(":/images/single_play.png"));
    }
    else
    {
        qDebug()<<"暂不⽀持该模式";
    }
}

//播放模式的切换
void QQMusic::onPlaybackModeCliked()
{
    if(playList->playbackMode() == QMediaPlaylist::Loop)
    {
        // 列表循环
        ui->playMode->setToolTip("随机播放");
        playList->setPlaybackMode(QMediaPlaylist::Random);
    }
    else if(playList->playbackMode() == QMediaPlaylist::Random)
    {
        // 随机播放
        ui->playMode->setToolTip("单曲循环");
        playList->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
    }
    else if(playList->playbackMode() == QMediaPlaylist::CurrentItemInLoop)
    {
        ui->playMode->setToolTip("列表循环");
        playList->setPlaybackMode(QMediaPlaylist::Loop);
    }
    else
    {
        qDebug()<<"播放模式错误";
    }
}

void QQMusic::onPlayAll(PageType pageType)
{
    CommonPage*page=nullptr;
    switch (pageType)
    {
    case LOCAL_PAGE:
        page=ui->localpage;
        break;
    case LIKE_PAGE:
        page=ui->likepage;
        break;
    case HISTORY_PAGE:
        page=ui->recentpage;
    default:
        qDebug()<<"拓展";
        break;
    }
    // 从当前⻚⾯的零号位置开始播放
    playAllOfCommonPage(page, 0);
}

void QQMusic::playAllOfCommonPage(CommonPage *commonPage, int index)
{
    curPage=commonPage;
    // 播放page所在⻚⾯的⾳乐
    // 将播放列表先清空，否则⽆法播放当前CommonPage⻚⾯的歌曲
    // 另外：该⻚⾯⾳乐不⼀定就在播放列表中，因此需要先将该⻚⾯⾳乐添加到播放列表
    playList->clear();
    // 202
    commonPage->addMusicToPlayer(musicList, playList);
    // 设置当前播放列表的索引
    playList->setCurrentIndex(index);
    // 播放
    player->play();
}

void QQMusic::playMusicByIndex(CommonPage *page, int index)
{
    currentIndex=index;
    playAllOfCommonPage(page, index);
}

void QQMusic::onCurrentIndexChanged(int index)
{
    currentIndex=index;
    // ⾳乐的id都在commonPage中的musicListOfPage中存储着
    const QString& musicId = curPage->getMusicIdByIndex(index);
    // 有了MusicId就可以再musicList中找到该⾳乐
    auto it = musicList.findMusicById(musicId);
    if(it != musicList.end())
    {
        // 将该⾳乐设置为历史播放记录
        it->setIsHistory(true);
    }
    ui->recentpage->reFresh(musicList);

}

void QQMusic::setMusicSilence(bool isMuted)
{
    player->setMuted(isMuted);

}

void QQMusic::setPlayerVolume(int volume)
{
    player->setVolume(volume);
}

void QQMusic::onDurationChanged(qint64 duration)
{
    totalTime=duration;
    ui->totalTime->setText(QString("%1:%2").arg(duration/1000/60,2,10,QChar('0'))
                           .arg(duration/1000%60,2,10,QChar('0')));
}

void QQMusic::onpositionChanged(qint64 position)
{
    ui->currentTime->setText(QString("%1:%2").arg(position/1000/60,2,10,QChar('0'))
                             .arg(position/1000%60,2,10,QChar('0')));
    ui->processBar->setStep(position/(float)totalTime);
    lrcPage->showLrcWordLine(position);
}

void QQMusic::onMusicSliderChanged(float value)
{
    // 1. 计算当前seek位置的时⻓
    qint64 duration = totalTime*value;
    // 2. 转换为百分制，设置当前时间
    ui->currentTime->setText(QString("%1:%2").arg(duration/1000/60, 2, 10,QChar('0'))
                             .arg(duration/1000%60, 2, 10, QChar('0')));
    // 3. 设置当前播放位置
    player->setPosition(duration);
}

void QQMusic::onMetaDataAvailableChangedChanged(bool available)
{
    QString musicId=curPage->getMusicIdByIndex(currentIndex);
    auto it=musicList.findMusicById(musicId);
    QString musicName("未知歌曲");
    QString singerName("未知歌手");
    if(it!=musicList.end())
    {
        musicName=it->getMusicName();
        singerName=it->getSingerName();
    }
    ui->musicName->setText(musicName);
    ui->musicSinger->setText(singerName);
    // 3. 获取封⾯图⽚
    QVariant coverImage = player->metaData("ThumbnailImage");
    if(coverImage.isValid())
    {
        // 获取封⾯图⽚成功
        QImage image = coverImage.value<QImage>();
        // 设置封⾯图⽚
        ui->musicCover->setPixmap(QPixmap::fromImage(image));
        curPage->setMusicImage(QPixmap::fromImage(image));
    }
    else
    {
        // 设置默认图⽚-修改
        QString path =":/images/rec/001.png";
        ui->musicCover->setPixmap(path);
        curPage->setMusicImage((path));
        qDebug()<<"歌曲没有封⾯图⽚";
    }
    ui->musicCover->setScaledContents(true);
    if(it!=musicList.end())
    {
        QString lrcPath=it->getLrcFilepath();
        lrcPage->parseLrcFile(lrcPath);
    }

}

void QQMusic::onLrcWordClicked()
{
    lrcPage->show();
    lrcAnimation->start();
}





void QQMusic::initSQLite()
{
    //进行数据库驱动加载
    QSqlDatabase sqlite=QSqlDatabase::addDatabase("QSQLITE");
    //设置数据库名称
    sqlite.setDatabaseName("QQMusic.db");
    //打开
    if(!sqlite.open())
    {
        QMessageBox::critical(this,"QQMusic","数据库打开失败");
        return;
    }
    qDebug()<<"数据库连接成功";
    //创建表
    QString sql="CREATE TABLE IF NOT EXISTS MusicInfo(\
                    id INTEGER PRIMARY KEY AUTOINCREMENT,\
                    musicID varchar(50) UNIQUE,\
                    musicName  varchar(50),\
                    SingerName  varchar(50),\
                    albumName  varchar(50),\
                    musicUrl  varchar(256),\
                    duration BIGINT,\
                    isLike INTEGER,\
                    isHistory INTEGER)";
    QSqlQuery query;
    if(!query.exec(sql))
    {
        QMessageBox::critical(this,"QQMusic","初始化错误");
        return;
    }
    qDebug()<<"QQMusic表创建成功";

}

void QQMusic::iniMUsicList()
{
    musicList.readFromDB();
    ui->likepage->setMusicListType(PageType::LIKE_PAGE);
    ui->likepage->reFresh(musicList);
    ui->localpage->setMusicListType(PageType::LOCAL_PAGE);
    ui->localpage->reFresh(musicList);
    ui->recentpage->setMusicListType(PageType::HISTORY_PAGE);
    ui->recentpage->reFresh(musicList);

}

void QQMusic::on_skin_clicked()
{
    QMessageBox::information(this, "温馨提⽰", "⼩哥哥正在加班紧急⽀持中...");
}

void QQMusic::on_min_clicked()
{
    showMinimized();
}

void QQMusic::updateBtformAnimal()
{
    // 获取currentPage在stackedWidget中的索引
    int index = ui->stackedWidget->indexOf(curPage);
    if(-1 == index)
    {
        qDebug()<<"该⻚⾯不存在";
        return;
    }
    // 获取QQMusci界⾯上所有的btForm
    QList<btForm*> btForms = this->findChildren<btForm*>();
    for(auto btForm : btForms)
    {
        if(btForm->getpageId() == index)
        {
            // 将currentPage对⻥竿的btForm找到了
            btForm->showAnimal(true);
        }
        else
        {
            btForm->showAnimal(false);
        }
    }
}

void QQMusic::quitQQMusic()
{
    // 歌曲信息写⼊数据库
     musicList.writeToDB();
     // 断开与SQLite的链接
     sqlite.close();
     // 关闭窗⼝
     close();
}


































